package com.inspinia.base.util;

//import com.centnet.base.util.properties.FtpConfig;

import com.inspinia.base.common.exception.BusinessException;
import org.apache.commons.io.monitor.FileAlterationListener;
import org.apache.commons.io.monitor.FileAlterationMonitor;
import org.apache.commons.io.monitor.FileAlterationObserver;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.net.SocketException;

/**
 * ftp服务器上传下载处理类
 * <p>
 * Created by baozhennan on 2016/8/11.
 * <p>
 * 应用实例：
 * <p>
 * //监听本地
 * File file = new File("G:/sharedFolder/");
 * FtpUtil.FileListenerAdaptor(file,new FileAlterationListener(){
 *
 * @Override public void onStart(FileAlterationObserver fileAlterationObserver) {
 * System.out.println("開始掃描指定目錄");
 * }
 * @Override public void onDirectoryCreate(File file) {
 * System.out.println(file.getAbsolutePath()+"目錄被創建");
 * }
 * @Override public void onDirectoryChange(File file) {
 * System.out.println(file.getAbsolutePath()+"目錄被修改");
 * }
 * @Override public void onDirectoryDelete(File file) {
 * System.out.println(file.getAbsolutePath()+"目錄被刪除");
 * }
 * @Override public void onFileCreate(File file) {
 * System.out.println(file.getAbsolutePath()+"文件被創建");
 * }
 * @Override public void onFileChange(File file) {
 * System.out.println(file.getAbsolutePath()+"文件被修改");
 * }
 * @Override public void onFileDelete(File file) {
 * System.out.println(file.getAbsolutePath()+"文件被刪除");
 * }
 * @Override public void onStop(FileAlterationObserver fileAlterationObserver) {
 * System.out.println("掃描結束");
 * }
 * }, 6000L);
 * //下载文件
 * FtpUtil.downFileOrDir("/centnet/document/write/call/build.xml","G:/sharedFolder/build112.xml");
 * FtpUtil.downFileOrDir("/centnet/document/write/call/", "G:/sharedFolder/");
 * //上传文件
 * FtpUtil.upLoadFileOrDir("G:/test3/","/centnet/document/write/call/");
 * FtpUtil.upLoadFileOrDir("G:/test3/build.xml", "/centnet/document/write/call/buildftp.xml");
 * FtpUtil.connect();
 * //删除文件
 * FtpUtil.deleteFtpFiles("/centnet/document/write/call/");
 * FtpUtil.deleteFtpFiles("/centnet/document/write/call/build.xml");
 * <p>
 * </p>
 */


public class FtpUtil {

    protected static Logger logger = LoggerFactory.getLogger(FtpUtil.class);

//    //用户名
//    public static final String userName = FtpConfig.userName;
//    //用户密码
//    public static final String password = FtpConfig.password;
//    //ftp的Ip地址
//    public static final String ftpHostName = FtpConfig.host;
//    //ftp的端口号
//    public static final int port = FtpConfig.port;

    /**
     * 链接ftp
     *
     * @param ip       地址
     * @param port     端口号
     * @param user     用户名
     * @param password 密码
     * @param path     路径
     */
    public static FTPClient connectServer(String ip, int port, String user, String password, String path) {
        try {
            FTPClient ftpClient = new FTPClient();
            ftpClient.connect(ip, port);
            // FTP服务器连接回答
            int reply = ftpClient.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply)) {
                ftpClient.disconnect();
            }
            ftpClient.login(user, password);
            ftpClient.setBufferSize(256);
            ftpClient.changeWorkingDirectory(path);
            // 设置传输协议,设置文件传输类型为二进制
            ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
            ftpClient.setControlEncoding("UTF-8");
            return ftpClient;
        } catch (SocketException e) {
            logger.error("connect to fpt config fail", e);
            throw new BusinessException("录音服务器异常！");
        } catch (IOException e) {
            logger.error("connect to fpt config fail", e);
            throw new BusinessException("录音服务器异常！");
        }
    }

    /**
     * 关闭FTP服务器连接
     *
     * @data 2014-6-10 下午1:51:40
     */
    public static void closeFtp(FTPClient ftpClient, OutputStream os) {
        if (os != null) {
            try {
                os.close();
            } catch (IOException e) {
                logger.error("", e);
            }
        }

        if (null != ftpClient && ftpClient.isConnected()) {
            try {
                boolean rs = ftpClient.logout();
                if (rs) {
                    logger.info("logout ftp config:" + ftpClient.getPassiveHost());
                }
            } catch (IOException e) {
                logger.error("logout ftp config" + ftpClient.getPassiveHost() + "failed", e);
            } finally {
                try {
                    ftpClient.disconnect();
                } catch (IOException e) {
                    logger.error("logout ftp config" + ftpClient.getPassiveHost() + "failed", e);
                }
            }
        }
    }


    /**
     * 建立连接
     */
    public static FTPClient connect(String ftpHostName, int port, String userName, String password) throws IOException {
        FTPClient ftpClient = new FTPClient();
        ftpClient.connect(ftpHostName, port);
        // FTP服务器连接回答
        int reply = ftpClient.getReplyCode();
        if (!FTPReply.isPositiveCompletion(reply)) {
            ftpClient.disconnect();
        }
        ftpClient.login(userName, password);
        ftpClient.setBufferSize(256);
        // 设置传输协议,设置文件传输类型为二进制
        ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
        ftpClient.setControlEncoding("UTF-8");
        return ftpClient;
    }

    /**
     * 关闭输入输出流
     *
     * @param fos       输出流
     * @param ftpClient ftp客户端
     */
    public static void close(FileOutputStream fos, FTPClient ftpClient) throws IOException {
        if (fos != null) {
            fos.close();
        }
        // 退出FTP服务器
        ftpClient.logout();
        // 关闭FTP服务器的连接
        ftpClient.disconnect();
    }

    /**
     * 关闭输入输入流
     *
     * @param fis       输入流
     * @param ftpClient ftp客户端
     */
    public static void close(FileInputStream fis, FTPClient ftpClient) throws IOException {
        if (fis != null) {
            fis.close();
        }
        // 退出FTP服务器
        ftpClient.logout();
        // 关闭FTP服务器的连接
        ftpClient.disconnect();
    }

    /**
     * 查询某目录下所有下文件目录
     *
     * @return
     */
    public static String[] getListFiles(FTPClient ftpClient, String path) {
        String files[] = null;
        try {
            if (null == path || "".equals(path)) {
                path = "/";
            }
            files = ftpClient.listNames(path);
        } catch (IOException e) {
            logger.error("get file list from  config" + ftpClient.getPassiveHost() + "failed", e);
        }
        return files;
    }

    /**
     * 上传文件
     *
     * @param localDir   本地文件目录
     * @param ftpFileDir ftp文件目录
     */
    public static void upLoadFileOrDir(String localDir, String ftpFileDir, FTPClient ftpClient) throws IOException {
        FileInputStream fis = null;
        upLoadFileOrDirHandle(localDir, ftpFileDir, ftpClient, fis);

        close(fis, ftpClient);
    }

    /**
     * 上传文件具体处理
     *
     * @param localDir   本地文件目录
     * @param ftpFileDir ftp文件目录
     * @param ftpClient  ftp客户端
     * @param fis        输入流
     */
    public static void upLoadFileOrDirHandle(String localDir, String ftpFileDir, FTPClient ftpClient, FileInputStream fis) throws IOException {
        File temp = new File(localDir);

        //判断localDir是否是一个文件夹，如果是文件夹，则将文件夹下的文件拷贝到ftpFileDir下；如果是文件（用于重命名），则将该文件拷贝到ftpFileDir并以ftpFileDir的最后一个节点命名
        if (temp.isDirectory()) {
            //判断ftp服务器是否有这个路径，没有就创建
            if (!isDir(ftpFileDir, ftpClient)) {
                ftpClient.makeDirectory(new String(ftpFileDir.getBytes("UTF-8"), "iso-8859-1"));

            }
            File[] files = temp.listFiles();
            String[] fileNames = new String[files.length];
            for (int i = 0; i < files.length; i++) {
                fileNames[i] = files[i].getAbsolutePath();
                //判断files[i]是否是文件夹
                if (files[i].isDirectory()) {
                    upLoadFileOrDirHandle(files[i].getAbsolutePath().replace("\\", "/") + "/", ftpFileDir + fileNames[i].substring(fileNames[i].lastIndexOf("\\") + 1) + "/", ftpClient, fis);
                } else {
                    fis = new FileInputStream(files[i]);
                    ftpClient.changeWorkingDirectory("/");
                    ftpClient.setBufferSize(1024);
                    //进行转码
                    ftpClient.setControlEncoding("UTF-8");
                    ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
                    ftpClient.storeFile(new String((ftpFileDir + fileNames[i].substring(fileNames[i].lastIndexOf("\\") + 1)).getBytes("UTF-8"), "iso-8859-1"), fis);

                }
            }
        } else {
            fis = new FileInputStream(new File(localDir));
            ftpClient.changeWorkingDirectory("/");
            ftpClient.setBufferSize(1024);
            ftpClient.setControlEncoding("UTF-8");
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
            ftpClient.storeFile(new String(ftpFileDir.getBytes("UTF-8"), "iso-8859-1"), fis);

        }

    }

    /**
     * 下载文件
     *
     * @param ftpFileDir ftp文件路径
     * @param localDir   本地文件路径
     */
    public static void downFileOrDir(String ftpFileDir, String localDir, FTPClient ftpClient) throws IOException {
        FileOutputStream fos = null;
        downFileOrDirHandle(ftpFileDir, localDir, ftpClient, fos);
        close(fos, ftpClient);
    }


    /**
     * 下载文件具体处理
     *
     * @param ftpFileDir ftp目录
     * @param localDir   本地目录
     * @param ftpClient  ftp客户端
     * @param fos        输出流
     */
    public static void downFileOrDirHandle(String ftpFileDir, String localDir, FTPClient ftpClient, FileOutputStream fos) throws IOException {
        File temp = new File(localDir);
        ftpClient.setControlEncoding("UTF-8");
        // 判断是否是目录
        if (isDir(ftpFileDir, ftpClient)) {

            if (!temp.exists()) {
                temp.mkdirs();
            }

            String[] names = ftpClient.listNames();
            for (int i = 0; i < names.length; i++) {

                if (isDir(names[i], ftpClient)) {
                    downFileOrDirHandle(ftpFileDir + '/' + names[i], localDir
                            + File.separator + names[i], ftpClient, fos);
                    ftpClient.changeToParentDirectory();
                } else {
                    File localFile = new File(localDir + File.separator
                            + names[i]);
                    if (!localFile.exists()) {
                        System.out.println("下载的文件以及文件夹:" + names[i]);
                        fos = new FileOutputStream(localFile);
                        ftpClient.retrieveFile(new String(names[i].getBytes("UTF-8"), "iso-8859-1"), fos);
                    }
                }
            }
        } else {
            if (!temp.exists()) {
                fos = new FileOutputStream(temp);
                ftpClient.retrieveFile(new String(ftpFileDir.getBytes("UTF-8"), "iso-8859-1"), fos);
            }
            ftpClient.changeToParentDirectory();
        }
    }

    /**
     * 判断是否是目录
     *
     * @param fileName
     * @return
     */
    public static boolean isDir(String fileName, FTPClient ftpClient) throws IOException {
        // 切换目录，若当前是有目录则返回true,否则返回false
        return ftpClient.changeWorkingDirectory(new String(fileName.getBytes("UTF-8"), "iso-8859-1"));
    }

    /**
     * 监听本地文件夹
     *
     * @param localFile                监听文件路径
     * @param myFileAlterationListener 收听器
     * @param time                     多久扫描一次，单位是ms
     */
    public static void FileListenerAdaptor(File localFile, FileAlterationListener myFileAlterationListener, Long time) throws Exception {
        FileAlterationObserver fileAlterationObserver = new FileAlterationObserver(localFile);
        fileAlterationObserver.addListener(myFileAlterationListener);
        FileAlterationMonitor fileAlterationMonitor = new FileAlterationMonitor(time, fileAlterationObserver);
        fileAlterationMonitor.start();
    }

    /**
     * 删除ftp服务器的文件
     *
     * @param ftpFileDir ftp服务器文件目录
     * @throws IOException
     */
    public static void deleteFtpFiles(String ftpFileDir, FTPClient ftpClient) throws IOException {
        deleteFtpFilesHandle(ftpFileDir, ftpClient);
        if (isDir(ftpFileDir, ftpClient)) {
            if (!ftpFileDir.endsWith("/")) {
                ftpFileDir = ftpFileDir + "/";
            }
            ftpClient.removeDirectory(new String(ftpFileDir.getBytes("UTF-8"), "iso-8859-1"));
        }
        ftpClient.logout();
        ftpClient.disconnect();
    }

    /**
     * 删除ftp服务器的文件具体处理
     *
     * @param ftpFileDir ftp服务器文件目录
     */
    public static void deleteFtpFilesHandle(String ftpFileDir, FTPClient ftpClient) throws IOException {
        //判断是否是目录
        if (isDir(ftpFileDir, ftpClient)) {
            if (!ftpFileDir.endsWith("/")) {
                ftpFileDir = ftpFileDir + "/";

            }
            ftpClient.setControlEncoding("UTF-8");
            FTPFile[] files = ftpClient.listFiles(new String(ftpFileDir.getBytes("UTF-8"), "iso-8859-1"));
            if (files == null || files.length <= 0) {
                //文件夹文空直接删除
                ftpClient.removeDirectory(new String(ftpFileDir.getBytes("UTF-8"), "iso-8859-1"));
            }
            for (FTPFile f : files) {
                if (f.isDirectory()) {
                    //文件夹不为空，先删文件再删文件夹
                    deleteFtpFilesHandle(ftpFileDir + f.getName(), ftpClient);
                    ftpClient.removeDirectory(new String((ftpFileDir + f.getName()).getBytes("UTF-8"), "iso-8859-1"));
                }
                if (f.isFile()) {
                    ftpClient.deleteFile(new String((ftpFileDir + f.getName()).getBytes("UTF-8"), "iso-8859-1"));
                }
            }
        } else {
            ftpClient.deleteFile(new String((ftpFileDir).getBytes("UTF-8"), "iso-8859-1"));
        }
    }

    /**
     * 下载文件
     *
     * @param ftpClient      自定义的客户端
     * @param localFilePath  本地文件
     * @param remoteFileName 远程文件
     * @return
     */
    public static boolean downFile(FTPClient ftpClient, String localFilePath, String remoteFileName) {
        BufferedOutputStream outStream = null;
        boolean rs = false;
        try {
            File file = new File(localFilePath);
            File parent = file.getParentFile();
            parent.mkdirs();
            if (!file.exists()) {
                file.createNewFile();
            }
            outStream = new BufferedOutputStream(new FileOutputStream(localFilePath));
            rs = ftpClient.retrieveFile(remoteFileName, outStream);
            return rs;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            logger.error("", e);
        } catch (IOException e) {
            logger.error("", e);
        } finally {
            closeFtp(ftpClient, outStream);
        }
        return rs;
    }
}


